/** 
 * DownloadTask.java
 * @author Lex
 * 2007-9-6 ����07:56:43
 */
package org.lex.ftp.queue;

import java.io.*;
import javax.swing.Icon;

import org.lex.ftp.FTP;
import org.lex.ftp.model.FTPModel;
import org.lex.ftp.ui.explorer.FTPExplorer;
import org.lex.ftp.util.prefs.FileAction;
import org.lex.ftp.util.prefs.FileActions;
import org.lex.io.IO;
import org.lex.io.NullInputStream;
import org.lex.io.NullOutputStream;
import org.lex.io.filesystem.FileNameUtilities;
import org.lex.net.ftp.IFTPClient;
import org.lex.net.ftp.IFTPFile;


public class DownloadTask extends XloadTask {
	private String fullFtpPath = null;
	private boolean skip = false;
	private boolean resume = false;
	private long offset = -1;
	final Object disposer = new Object() {
		protected void finalize() throws Throwable {
			dispose();
		}
	};

	public DownloadTask(FTP app, String ftpPath, IFTPFile ftpFile, File file) {
		super(app, ftpPath, ftpFile, file);
		this.fullFtpPath = FileNameUtilities.getFullPath(ftpPath, ftpFile.getName(), '/');
	}

	public Icon getIcon() {
		return TaskIconUtils.getDownloadTaskIcon(this);
	}

	public String getSource() {
		return this.fullFtpPath;
	}

	public Icon getSourceIcon() {
		// ftpFile
		return this.getFTPFileIcon(ftpFile);
	}

	public String getDestination() {
		return file.getAbsolutePath();
	}

	public Icon getDestinationIcon() {
		// file
		return this.getFileIcon(file);
	}

	public String getDescription() {
		return "Download " + ftpFile.getName();
	}

	public long getLength() {
		return ftpFile.getSize();
	}

	public boolean hasChild() {
		return ftpFile.isDirectory();
	}

	public void expandChildren() {
		FTPExplorer ftpExplorer = app.getFTPExplorer();
		FTPModel model = ftpExplorer.getFTPModel();
		String pwd = model.getCatalog();
		if (false == pwd.equals(fullFtpPath))
			model.setCatalog(fullFtpPath);
		if (false == file.exists())
			file.mkdirs();
		app.getFileExplorer().setDirectory(file, true);
		QueueUtils.downloadCurrentCatalog(app);
	}

	// read from ftp
	private InputStream in = null;

	public InputStream openInputStream() throws IOException {
		if (null != in) {
			IO.closeQuietly(in);
			in = null;
		}
		if (true == skip)
			in = NullInputStream.getInstance();
		else {
			FTPModel model = this.app.getFTPExplorer().getFTPModel();
			String pwd = model.getCatalog();
			if (false == pwd.equals(ftpPath))
				model.setCatalog(ftpPath);
			IFTPClient ftp = model.getFTPClient();
			if (true == resume && -1 != this.offset)
				ftp.restart(offset);
			in = ftp.get(ftpFile.getName());
		}
		return in;
	}

	// write to file system
	private OutputStream out = null;

	public OutputStream openOutputStream() throws IOException {
		if (null != out) {
			IO.closeQuietly(out);
			out = null;
		}
		// open file
		File dir = file.getParentFile();
		if (false == dir.exists() || false == dir.isDirectory())
			dir.mkdirs();
		if (false == file.exists() || false == file.isFile()) {
			file.createNewFile();
			out = new FileOutputStream(file);
		} else {
			// file exists ,handle file exists action
			FileAction action = this.getFileAction(file, ftpFile);
			switch (action) {
			case OVERWRITE:
				out = new FileOutputStream(file, false);
				break;
			case SKIP:
				this.skip = true;
				out = NullOutputStream.getInstance();
				break;
			case RESUME:
				this.resume = true;
				this.offset = file.length();
				out = new FileOutputStream(file, true);
				break;
			}
		}
		return out;
	}

	/**
	 * ȷ�����᷵��FileAction.ASK
	 */
	private FileAction getFileAction(File exists, IFTPFile ftpFile) {
		FileAction action = FileActions.getInstance().getAction(FileActions.DOWNLOAD, exists.length(), ftpFile.getSize());
		// if action == ASK, show a dialog to ask user
		return action;
	}

	public void dispose() {
		IO.closeQuietly(out);
		IO.closeQuietly(in);
		super.dispose();
	}

	public String toString() {
		StringBuilder b = new StringBuilder();
		b.append("Download ");
		if (ftpFile.isDirectory())
			b.append("DIRECTORY");
		else
			b.append("FILE");
		b.append('\n');
		b.append("URL : ").append(app.getFTPExplorer().getFTPModel().getFTPURL().getServer()).append('\n');
		b.append("From: ").append(fullFtpPath).append('\n');
		b.append("To  : ").append(file.getAbsolutePath()).append('\n');
		return b.toString();
	}
}
